package consumer

import (
	"context"
	"device_mq_handler/internal/pkg/instance"
	_ "device_mq_handler/internal/protocol/jt808/handler"
	"device_mq_handler/internal/protocol/jt808/holder"
	"device_mq_handler/pkg/amqps"
	"gitee.com/lailonghui/vehicle-supervision-framework/pkg/asserts"
	"github.com/buger/jsonparser"
	"github.com/streadway/amqp"
	"go.uber.org/zap"
	"log"
)

func NewConsumer(ctx context.Context, conn *amqp.Connection) {
	channel, err := conn.Channel()
	asserts.Nil(err, err)

	// 设置请求参数，比如每次拉取多少数据
	err = channel.Qos(
		1,     // prefetch count
		0,     // prefetch size
		false, // global
	)
	asserts.Nil(err, err)

	// 请求消费数据
	msgs, err := channel.Consume(
		"jt808.common.writer", // queue
		"",                    // consumer
		false,                 // auto-ack
		false,                 // exclusive
		false,                 // no-local
		false,                 // no-wait
		nil,                   // args
	)
	asserts.Nil(err, err)

	go func() {
		defer func() {
			if x := recover(); x != nil {
				instance.GetAppLog().Error("panic", zap.Any("错误", x))
				return
			}
		}()
		for d := range msgs {
			log.Println(d.Headers)
			log.Printf("Received a message: %s", d.Body)
			log.Printf("Done")
			ctx := context.Background()
			err := ResolveMsg(ctx, &d)
			if err != nil {
				instance.GetAppLog().Error("处理808消息异常", zap.Error(err))
			}
		}
	}()
}

// 解析消息
func ResolveMsg(ctx context.Context, delivery *amqp.Delivery) (err error) {
	defer func() {
		if err != nil {
			_ = delivery.Nack(false, false)
			return
		}
		if x := recover(); x != nil {
			_ = delivery.Nack(false, false)
			return
		}
		_ = delivery.Ack(false)
	}()

	workId, err := jsonparser.GetInt(delivery.Body, "Head", "WorkId")
	if err != nil {
		instance.GetAppLog().Error("序列化错误", zap.Error(err))
	}
	return DoDispatch(ctx, workId, delivery.Body, delivery)
}

// 分发消息
func DoDispatch(ctx context.Context, workId int64, data []byte, d *amqp.Delivery) error {
	handler := holder.GetHandler(workId)
	if handler == nil {
		return amqps.NOT_HANDLER_FIND_ERROR
	}
	return handler(ctx, data, d)
}
